home *** CD-ROM | disk | FTP | other *** search
/ Die Speccy' 97 / Die Speccy' 97.iso / amiga_system / the_aminet / comm / tcp / mufs_telnetd.lha / telnetd2_0.lha / telnetd-2.0 / source / RCS / telnetd.c next >
C/C++ Source or Header  |  1995-04-13  |  79KB  |  2,150 lines

  1. head    2.0;
  2. access;
  3. symbols;
  4. locks; strict;
  5. comment    @ * @;
  6.  
  7.  
  8. 2.0
  9. date    95.04.13.19.53.48;    author simons;    state Exp;
  10. branches;
  11. next    1.11;
  12.  
  13. 1.11
  14. date    95.04.13.18.50.17;    author simons;    state Exp;
  15. branches;
  16. next    1.10;
  17.  
  18. 1.10
  19. date    95.02.03.00.25.28;    author simons;    state Exp;
  20. branches;
  21. next    1.9;
  22.  
  23. 1.9
  24. date    95.01.26.22.20.38;    author simons;    state Exp;
  25. branches;
  26. next    1.8;
  27.  
  28. 1.8
  29. date    95.01.24.00.12.47;    author simons;    state Exp;
  30. branches;
  31. next    1.7;
  32.  
  33. 1.7
  34. date    95.01.23.23.51.39;    author simons;    state Exp;
  35. branches;
  36. next    1.6;
  37.  
  38. 1.6
  39. date    95.01.23.23.42.48;    author simons;    state Exp;
  40. branches;
  41. next    1.5;
  42.  
  43. 1.5
  44. date    95.01.23.23.35.13;    author simons;    state Exp;
  45. branches;
  46. next    1.4;
  47.  
  48. 1.4
  49. date    95.01.23.22.54.44;    author simons;    state Exp;
  50. branches;
  51. next    1.3;
  52.  
  53. 1.3
  54. date    95.01.23.22.19.28;    author simons;    state Exp;
  55. branches;
  56. next    1.2;
  57.  
  58. 1.2
  59. date    95.01.23.21.59.56;    author simons;    state Exp;
  60. branches;
  61. next    1.1;
  62.  
  63. 1.1
  64. date    95.01.22.18.07.20;    author simons;    state Exp;
  65. branches;
  66. next    ;
  67.  
  68.  
  69. desc
  70. @TelnetGetty is called by TnServ and handles the login.
  71. When a correct user is logged in, it executes the listed
  72. command.
  73. @
  74.  
  75.  
  76. 2.0
  77. log
  78. @Updated my e-mail address to .rhein.de.
  79. Replaced one if-construct with the more efficient ?: operator.
  80. The processname of telnetd is now set to reflect the username
  81. of the user that logged in.
  82. Added LOG_INFO type messages when a login failed or was successful.
  83. @
  84. text
  85. @/*
  86.  *      $Filename: telnetd.c $
  87.  *      $Revision: 1.11 $
  88.  *      $Date: 1995/04/13 18:50:17 $
  89.  *
  90.  *      Copyright (C) 1993,94 by Steve Holland <sdh4@@cornell.edu>
  91.  *      Copyright (C) 1995 by Peter Simons <simons@@peti.rhein.de>
  92.  *
  93.  *      This program is free software; you can redistribute it and/or
  94.  *      modify it under the terms of the GNU General Public License as
  95.  *      published by the Free Software Foundation; either version 2 of
  96.  *      the License, or (at your option) any later version.
  97.  *
  98.  *      This program is distributed in the hope that it will be useful,
  99.  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
  100.  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  101.  *      General Public License for more details.
  102.  *
  103.  *      You should have received a copy of the GNU General Public License
  104.  *      along with this program; if not, write to the Free Software
  105.  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  106.  *
  107.  *      $Id: telnetd.c 1.11 1995/04/13 18:50:17 simons Exp simons $
  108.  *
  109.  */
  110.  
  111. /************************************* includes ***********/
  112. #include <exec/types.h>
  113. #include <exec/memory.h>
  114. #include <sys/types.h>
  115. #include <sys/socket.h>
  116. #include <sys/param.h>
  117. #include <dos/dos.h>
  118. #include <dos/dosextens.h>
  119. #include <dos/dostags.h>
  120. #include <proto/dos.h>
  121. #include <proto/exec.h>
  122. #include <proto/utility.h>
  123. #include <proto/usergroup.h>
  124. #include <errno.h>
  125. #include <sys/ioctl.h>
  126. #include <exec/errors.h>
  127. #include <devices/serial.h>
  128. #include <string.h>
  129. #include <stdlib.h>
  130. #include <stdio.h>
  131. #include <inetd.h>
  132. #include <syslog.h>
  133. #include <amitcp/socketbasetags.h>
  134.  
  135. #include <fakesr.h>
  136.  
  137. #include "telnetd_rev.h"
  138.  
  139. /************************************* structures *********/
  140. struct InstData {
  141.         struct Library *DOSB;
  142.         struct Library *SocketB;
  143.         struct Library *UtilityB;
  144.         struct Library *UserGroupB;
  145.         int Socket;
  146.         signed short RecvBuf[1024];
  147.         int RecvBufPos;
  148.         int RecvBufFlags;
  149. };
  150.  
  151. struct PasswdInfo {
  152.         char Login[50];
  153.         char Passwd[50];
  154.         char RealName[150];
  155.         char WorkDir[256];
  156.         char Command[512];
  157. };
  158.  
  159. /************************************* defines ************/
  160. #define DOSBase Inst->DOSB
  161. #define UtilityBase Inst->UtilityB
  162. #define SocketBase Inst->SocketB
  163. #define UserGroupBase Inst->UserGroupB
  164. #define Socket Inst->Socket
  165.  
  166. /* telnet symbols */
  167. #define IAC 255
  168. #define WILL 251
  169. #define WONT 252
  170. #define DO 253
  171. #define DONT 254
  172. #define ECHO 1
  173. #define LINEMODE 34
  174. #define SE 240
  175. #define SB 250
  176. #define MODE 1
  177. #define EDIT 1
  178.  
  179. #define RBF_SUBNEGOTIATE (1<<0)         /* Defines for RecvBufFlags */
  180.  
  181. /************************************* global variables ***/
  182. static const char __DOSVer[] = VERSTAG " written by Peter Simons <simons@@peti.rhein.de>";
  183. #ifndef USE_INETD
  184. struct Library *SysBase;
  185. #endif
  186. char *Signature="FAKEMSG--EXPUNGE";
  187.  
  188. /************************************* prototypes *********/
  189. void SockPuts(struct InstData *Inst,int Sock,char *Buf);
  190. void SockGets(struct InstData *Inst,int Sock,char *Buf,int BufSize);
  191. unsigned long GetInt(char *String,char **NewPtr);
  192. struct PasswdInfo *LookupPasswd(struct InstData *Inst,char *Login);
  193. int __asm SubSubProc(register __a0 char *ArgString,register __d0 long Length);
  194. struct DosPacket *PktFromMsg(struct Message *Msg);
  195. void MakeLongStr(char *StrBuf,unsigned long Num);
  196. void SockWrite(struct InstData *Inst,int Sock,char *Buf,int Len,int RawFlag);
  197. int RecvChar(struct InstData *Inst,int Sock,unsigned char *Loc,int RawMode);
  198. struct Process *MyCreateNewProcTags(struct InstData *,ULONG,...);
  199. void *MyAllocDosObjectTags(struct InstData *,ULONG,ULONG,...);
  200. void PktFPuts(struct InstData *Inst,BPTR File,char *String);
  201. void SockRawWrite(struct InstData *Inst,int Sock,char *Buf,int Len);
  202. void MySystemTags(struct Library *DSBse,char *Cmd,ULONG Tag0,...);
  203. void mystrcat(char *Dest,char *Cat);
  204. void MyFPrintf(struct InstData *Inst,BPTR File,char *Fmt,...);
  205.  
  206. ULONG FakeBeginIO(void *IORequest);
  207. ULONG FakeAbortIO(void *IORequest);
  208. ULONG FakeOpen(void *IORequest);
  209. ULONG FakeClose(void *IORequest);
  210. void mymovmem(char *From,char *To,int Len);
  211.  
  212. #define NewList(list) {(list)->lh_Head=(struct Node *)&(list)->lh_Tail;(list)->lh_Tail=NULL;(list)->lh_TailPred=(struct Node *)&(list)->lh_Head;}
  213.  
  214. #ifdef DEBUG
  215.   BPTR DebugFile;
  216. #endif
  217.  
  218. #ifdef USE_INETD
  219. int main(void)
  220. #else
  221. int __asm main(register __a0 char *ArgStr,register __d0 long Length)
  222. /* ArgString will look like: "[SocketID] [SigNum] [ParentTaskID]" */
  223. #endif
  224. {
  225.         int Cnt;
  226.         unsigned long SockID,SigID,TaskID;
  227.         char Buf[1000],LoginBuf[50], MyPrgName[64];
  228.         BPTR BannerFile=NULL;
  229.         struct InstData *Inst=NULL;
  230.         struct PasswdInfo *Info=NULL;
  231.         struct FileHandle *FH;
  232.         struct Message *Msg,*GotMsg;
  233.         unsigned char NoEcho[7];
  234.         unsigned char Echo[14];
  235.         char *ArgString;
  236.         int OpenCount=0;
  237.         int AmntRead;
  238.         int HangupFlag=FALSE;
  239.  
  240.         ULONG SigMask;
  241.         long yes=TRUE;
  242.         fd_set RdSet;
  243.         fd_set WrSet;
  244.         struct List ReadWaitList;
  245.         struct DosPacket *Pkt;
  246.         int Err;
  247.         unsigned char Chr,NumBuf[30];
  248.         int RawMode=FALSE;
  249.         int NextChar=-1;
  250.         struct MsgPort *TimePort;
  251.         struct timerequest *TimeReq;
  252.         struct DaemonMessage *InetdStartup;
  253.         struct Process *Self;
  254.  
  255.  
  256. #ifndef USE_INETD
  257.         SysBase=*((struct Library **)0x00000004);
  258.         ArgString=ArgStr;
  259. #endif
  260.         Echo[0]=NoEcho[0]=IAC;
  261.         Echo[1]=WONT;
  262.         Echo[2]=ECHO;
  263.         Echo[3]=IAC;
  264.         Echo[4]=DO;
  265.         Echo[5]=LINEMODE;
  266.         Echo[6]=IAC;
  267.         Echo[7]=SB;
  268.         Echo[8]=LINEMODE;
  269.         Echo[9]=MODE;
  270.         Echo[10]=EDIT;
  271.         Echo[11]=IAC;
  272.         Echo[12]=SE;
  273.         NoEcho[1]=WILL;
  274.         NoEcho[2]=ECHO;
  275.         NoEcho[3]=IAC;
  276.         NoEcho[4]=DONT;
  277.         NoEcho[5]=LINEMODE;
  278.         Echo[13]=NoEcho[6]='\0';
  279.  
  280. #ifndef USE_INETD
  281.         for (Cnt=0;Cnt < Length;Cnt++) {
  282.                 if (ArgStr[Cnt]!=' ' && (ArgStr[Cnt] < '0' || ArgStr[Cnt] > '9'))
  283.                         return ERROR_FILE_NOT_OBJECT;
  284.         }
  285. #endif
  286.         Inst=AllocMem(sizeof(struct InstData),MEMF_CLEAR);
  287.         if (!Inst) return 0;
  288.         DOSBase=OpenLibrary("dos.library",36);
  289.         UtilityBase=OpenLibrary("utility.library",36);
  290.         SocketBase=OpenLibrary("bsdsocket.library",2);
  291.         UserGroupBase=OldOpenLibrary(USERGROUPNAME);
  292.  
  293.         TimePort=CreateMsgPort();
  294.         NewList(&ReadWaitList);
  295.  
  296.         if (!DOSBase || !UtilityBase || !SocketBase || !UserGroupBase || !TimePort) return 0;
  297.  
  298.         SocketBaseTags(SBTM_SETVAL(SBTC_LOGTAGPTR), "telnetd",
  299.                  SBTM_SETVAL(SBTC_LOGSTAT), 0,
  300.                  SBTM_SETVAL(SBTC_LOGFACILITY), LOG_AUTH,
  301.                  TAG_END);
  302.  
  303. #ifdef DEBUG
  304.         DebugFile=Open("con:0/0/500/100/telnetd DEBUG/WAIT/CLOSE",MODE_OLDFILE);
  305.         FPuts(DebugFile,"telnetd starting\n");
  306. #  ifndef USE_INETD
  307.         FPuts(DebugFile,"ArgString=");
  308.         FPuts(DebugFile,ArgString);
  309.         FPuts(DebugFile,"\n");
  310. #  endif
  311.  
  312. #endif
  313.  
  314. #ifdef USE_INETD
  315.         Self=(struct Process *) FindTask(NULL);
  316.         InetdStartup=(struct DaemonMessage *)Self->pr_ExitData;
  317.         if (!InetdStartup) goto quit;
  318.         Socket=ObtainSocket(InetdStartup->dm_Id,InetdStartup->dm_Family,InetdStartup->dm_Type,0);
  319.         if (Socket < 0) goto quit;
  320. #else
  321.         /* Get arguments */
  322.         SockID=GetInt(ArgString,&ArgString);
  323.         ArgString++; /* Skip over space */
  324.         SigID=GetInt(ArgString,&ArgString);
  325.         ArgString++; /* Skip over space */
  326.         TaskID=GetInt(ArgString,&ArgString);
  327.         /* After this call, the parameter string is no longer valid */
  328.         Signal((struct Task *)TaskID,1<<SigID);
  329. #ifdef DEBUG
  330.         FPuts(DebugFile,"Signaled parent\n");
  331. #endif
  332.  
  333.         /* We're on our own now */
  334.         Socket=ObtainSocket(SockID,AF_INET,SOCK_STREAM,0);
  335.         if (Socket < 0) goto quit;
  336.  
  337. #endif
  338.  
  339. #ifdef DEBUG
  340.         FPuts(DebugFile,"Got Socket\n");
  341. #endif
  342.  
  343.         /* First, display banner, ask for password, etc */
  344.         if (BannerFile=Open("AmiTCP:db/telnetd_banner",MODE_OLDFILE)) {
  345.                 int len = 1;
  346.  
  347.                 while(TRUE) {
  348.                         len = Read(BannerFile, Buf, sizeof(Buf));
  349.                         if (!len || len == -1)
  350.                                 break;
  351.                         SockWrite(Inst,Socket,Buf,len,FALSE);
  352.                 }
  353.                 Close(BannerFile);
  354.         }
  355.  
  356. #ifdef DEBUG
  357.         FPuts(DebugFile,"Wrote banner to socket\n");
  358. #endif
  359.         /* Get login name */
  360.         SockPuts(Inst,Socket,"Login: ");
  361.         SockPuts(Inst,Socket,Echo);
  362.         SockGets(Inst,Socket,LoginBuf,sizeof(LoginBuf));
  363.         while (strlen(LoginBuf) && (LoginBuf[strlen(LoginBuf)-1]=='\n' || LoginBuf[strlen(LoginBuf)-1]=='\r'))
  364.                 LoginBuf[strlen(LoginBuf)-1]='\0';
  365. #ifdef DEBUG
  366.         FPuts(DebugFile,"Got Login: ");
  367.         FPuts(DebugFile,LoginBuf);
  368.         FPuts(DebugFile,"\n");
  369. #endif
  370.  
  371.         Info = LookupPasswd(Inst, LoginBuf);
  372.  
  373.  
  374.         /*
  375.          * We don't need a password if the password is "*"
  376.          * AND the shell is not equal "nologin".
  377.          *
  378.          * Otherwise get a password, even if the user doesn't exist at all.
  379.          */
  380.         if (!Info || !(!strcmp(Info->Passwd, "*") && strcmp("nologin", Info->Command))) {
  381.                 strcpy(Buf, "Password: ");
  382.                 strcpy(Buf+strlen(Buf), NoEcho);
  383.                 SockPuts(Inst, Socket, Buf);
  384.                 SockGets(Inst, Socket, Buf,sizeof(Buf));
  385.                 while (strlen(Buf) && (Buf[strlen(Buf)-1]=='\n' || Buf[strlen(Buf)-1]=='\r'))
  386.                         Buf[strlen(Buf)-1]='\0';
  387.                 SockPuts(Inst,Socket,Echo);
  388. #ifdef DEBUG
  389.                 FPuts(DebugFile,"Got Password: ");
  390.                 FPuts(DebugFile,Buf);
  391.                 FPuts(DebugFile,"\n");
  392. #endif
  393.                 if (!Info || !strcmp("nologin", Info->Command) || strcmp(Info->Passwd, crypt(Buf, Info->Passwd))) {
  394.             if (Info)
  395.               syslog(LOG_INFO, "Unsuccessful login attempt from user %s", Info->Login);
  396.                         SockPuts(Inst,Socket,"\nLogin incorrect.\nClosing connection\n");
  397.                         CloseSocket(Socket);
  398.                         goto quit;
  399.                 }
  400.         }
  401.  
  402.         SockPuts(Inst,Socket,"\n");
  403.  
  404.     syslog(LOG_INFO, "User %s logged in successfully", Info->Login);
  405.     sprintf(MyPrgName, "telnetd <%s>", Info->Login);
  406.     SetProgramName(MyPrgName);
  407.  
  408.         if (Info->Command[0]=='*') {
  409.                 /* Use stdin/stdout */
  410.                 /* Make myself a filehandle */
  411. #ifdef DEBUG
  412.                 FPuts(DebugFile,"Logged in OK\nMaking Filehandle\n");
  413. #endif
  414.  
  415.                 FH=MyAllocDosObjectTags(Inst,DOS_FILEHANDLE,ADO_FH_Mode,MODE_OLDFILE,TAG_END);
  416.                 if (!FH) goto quit;
  417.                 FH->fh_Pos=FH->fh_End=-1;
  418.                 FH->fh_Type=&((struct Process *)FindTask(NULL))->pr_MsgPort;
  419.                 FH->fh_Args=(LONG)Info;
  420.                 FH->fh_Port=FH->fh_Type; /* Is this right? */
  421.                 FH=(struct FileHandle *)MKBADDR(FH);
  422.                 OpenCount++;
  423.  
  424.                 /* Run the subprocess */
  425.                 MakeLongStr(Buf,(ULONG)FH);
  426.                 strcpy(Buf+strlen(Buf)," ");
  427.                 strcpy(Buf+strlen(Buf),Info->Command+1 /* ignore the leading '*' */);
  428. #ifdef DEBUG
  429.                 FPuts(DebugFile,"Starting subprocess\nCmdLine=");
  430.                 FPuts(DebugFile,Buf);
  431.                 FPuts(DebugFile,"\n");
  432.                 /*Close(DebugFile);*/
  433.                 Flush(DebugFile);
  434.  
  435.                 /*DebugFile=NULL;*/
  436. #endif
  437.  
  438.                 /* NO more DOS calls allowed after this one */
  439.                 /* We also can't use Buf after we make this call */
  440.     if (*(Info->Command+1)) {
  441.                 MyCreateNewProcTags(Inst,NP_Entry,SubSubProc,
  442.                     NP_Arguments,Buf,
  443.                     TAG_END);
  444.     }
  445.                 FD_ZERO(&RdSet);
  446.                 IoctlSocket(Socket,FIONBIO,(caddr_t)&yes);
  447. #ifdef DEBUG
  448.                 PktFPuts(Inst,DebugFile,"Starting handler support\n");
  449. #endif
  450.                 for (;;) {
  451.                         if (ReadWaitList.lh_Head->ln_Succ && !HangupFlag) {
  452.                                 if (NextChar != -1) {
  453.                                         Pkt=PktFromMsg((struct Message *)ReadWaitList.lh_Head);
  454.                                         *(((unsigned char *)Pkt->dp_Arg2)+Pkt->dp_Res1)=NextChar;
  455.                                         Chr=NextChar;
  456.                                         NextChar=-1;
  457.                                         Err=1;
  458.                                         Pkt->dp_Res1++;
  459.                                         if (Pkt->dp_Res1==Pkt->dp_Arg3 || Chr=='\r' || Chr=='\n') {
  460.                                                 Remove(ReadWaitList.lh_Head);
  461.                                                 PutMsg(Pkt->dp_Port,Pkt->dp_Link); /* Send it back */
  462.                                         }
  463.                                 }
  464.                         }
  465.                         if (ReadWaitList.lh_Head->ln_Succ && !HangupFlag) {
  466.                                 FD_SET(Socket,&RdSet);
  467.                         } else {
  468.                                 FD_CLR(Socket,&RdSet);
  469.                         }
  470.                         SigMask=(1<<((struct Process *)FindTask(NULL))->pr_MsgPort.mp_SigBit)|(1<<TimePort->mp_SigBit);
  471.                         WaitSelect(Socket+1,&RdSet,NULL,NULL,NULL,&SigMask);
  472. #ifdef DEBUG
  473.                         PktFPuts(Inst,DebugFile,"Wait ended \n");
  474. #endif
  475.  
  476.                         if (FD_ISSET(Socket,&RdSet)) {
  477. #ifdef DEBUG
  478.                                 PktFPuts(Inst,DebugFile,"Got read available from socket\n");
  479. #endif
  480.                                 if (ReadWaitList.lh_Head->ln_Succ) {
  481.                                         /* Someone is waiting to read */
  482.                                         Pkt=PktFromMsg((struct Message *)ReadWaitList.lh_Head);
  483.                                         if (Pkt && Pkt->dp_Type==ACTION_READ) {
  484. #ifdef DEBUG
  485.                                                 PktFPuts(Inst,DebugFile,"Performing delayed read\n");
  486. #endif
  487.                                                 while (Pkt->dp_Res1 < Pkt->dp_Arg3) {
  488.                                                         if (NextChar != -1) {
  489.                                                                 *(((unsigned char *)Pkt->dp_Arg2)+Pkt->dp_Res1)=NextChar;
  490.                                                                 Chr=NextChar;
  491.                                                                 NextChar=-1;
  492.                                                                 Err=1;
  493.                                                         } else {
  494.                                                                 Err=RecvChar(Inst,Socket,((char *)Pkt->dp_Arg2)+Pkt->dp_Res1,FALSE/*RawMode*/);
  495.                                                                 Chr=*(((char *)Pkt->dp_Arg2)+Pkt->dp_Res1);
  496.                                                         }
  497.                                                         if (Err==1) Pkt->dp_Res1++;
  498.                                                         else if (Err==0) {
  499.                                                                 /* Hangup */
  500.                                                                 HangupFlag=TRUE;
  501.                                                                 break;
  502.                                                         } else break;
  503. #ifdef DEBUG
  504.                                                         if (Chr==255) {
  505.                                                                 PktFPuts(Inst,DebugFile,"Received 255\n");
  506.                                                         }
  507. #endif
  508.                                                         if (Chr=='\r' || Chr=='\n') {
  509.                                                                 break;
  510.                                                         }
  511.                                                 }
  512.                                                 if (Err==1) {
  513.                                                         if (Pkt->dp_Res1==Pkt->dp_Arg3 ||
  514.                                 Chr=='\r' || Chr=='\n') {
  515.                                                                 Remove(ReadWaitList.lh_Head);
  516. /*                                 syslog(LOG_DEBUG, "Sending out \"%s\"",
  517.  *                                        &Pkt->dp_Link+sizeof(struct Message));
  518.  */
  519.                                                                 PutMsg(Pkt->dp_Port,Pkt->dp_Link); /* Send it back */
  520.                                                         }
  521.                                                 }
  522.                                         } else if (Pkt && Pkt->dp_Type==ACTION_WAIT_CHAR) {
  523. #ifdef DEBUG
  524.                                                 PktFPuts(Inst,DebugFile,"Processing WAIT_CHAR");
  525. #endif
  526.                                                 if (NextChar==-1) {
  527.                                                         Err=RecvChar(Inst,Socket,&Chr,FALSE);
  528.                                                         if (Err==1) {
  529.                                                                 Pkt->dp_Res1=DOSTRUE;
  530.                                                                 Remove(ReadWaitList.lh_Head);
  531. #ifdef DEBUG
  532.                                                                 PktFPuts(Inst,DebugFile,"char ready\n");
  533. #endif
  534.                                                                 AbortIO((struct IORequest *)Pkt->dp_Res2);
  535.                                                                 WaitIO((struct IORequest *)Pkt->dp_Res2);
  536.                                                                 CloseDevice((struct IORequest *)Pkt->dp_Res2);
  537.                                                                 DeleteIORequest((struct IORequest *)Pkt->dp_Res2);
  538.                                                                 Pkt->dp_Res2=0;
  539.                                                                 PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  540.                                                                 NextChar=Chr;
  541.                                                         } else {
  542. #ifdef DEBUG
  543.                                                                 PktFPuts(Inst,DebugFile,"no char available\n");
  544. #endif
  545.                                                                 NextChar=-1;
  546.                                                         }
  547.                                                         if (Err==0) HangupFlag=TRUE;
  548.                                                 } else {
  549.                                                         Pkt->dp_Res1=DOSTRUE;
  550.                                                         Remove(ReadWaitList.lh_Head);
  551.                                                         AbortIO((struct IORequest *)Pkt->dp_Res2);
  552.                                                         WaitIO((struct IORequest *)Pkt->dp_Res2);
  553.                                                         CloseDevice((struct IORequest *)Pkt->dp_Res2);
  554.                                                         DeleteIORequest((struct IORequest *)Pkt->dp_Res2);
  555.                                                         Pkt->dp_Res2=0;
  556.                                                         PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  557. #ifdef DEBUG
  558.                                                         PktFPuts(Inst,DebugFile,"char ready\n");
  559. #endif
  560.                                                 }
  561.                                         }
  562.                                         else { /* Invalid message */
  563.                                                 Remove(ReadWaitList.lh_Head);
  564.                                         }
  565.                                 } else {
  566. #ifdef DEBUG
  567.                                         PktFPuts(Inst,DebugFile,"Unexpected: got read ready, no request\n");
  568. #endif
  569.                                 }
  570.                         }
  571.                         while (TimeReq=(struct timerequest *)GetMsg(TimePort)) {
  572.                                 Msg=(struct Message *)TimeReq->tr_node.io_Message.mn_Node.ln_Name;
  573.                                 Pkt=PktFromMsg(Msg);
  574.                                 CloseDevice(TimeReq);
  575.                                 DeleteIORequest(TimeReq);
  576.                                 Pkt->dp_Res1=DOSFALSE;
  577.                                 Pkt->dp_Res2=0;
  578.                                 Remove(Msg); /* Remove it from the read wait list */
  579.                                 PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  580.  
  581.  
  582.                         }
  583.                         while (Msg=GetMsg(&((struct Process *)FindTask(NULL))->pr_MsgPort)) {
  584.                                 Pkt=PktFromMsg(Msg);
  585. #ifdef DEBUG
  586.                                 PktFPuts(Inst,DebugFile,"Got packet\n");
  587. #endif
  588.                                 switch(Pkt->dp_Type) {
  589.                                         case ACTION_FINDINPUT:
  590.                                         case ACTION_FINDOUTPUT:
  591.                                         case ACTION_FINDUPDATE:
  592.                                                 FH=(struct FileHandle *)BADDR((BPTR)Pkt->dp_Arg1);
  593.                                                 FH->fh_Pos=FH->fh_End=-1;
  594.                                                 FH->fh_Type=&((struct Process *)FindTask(NULL))->pr_MsgPort;
  595.                                                 FH->fh_Args=(LONG)Info;
  596.                                                 FH->fh_Port=FH->fh_Type; /* Is this right? */
  597.                                                 OpenCount++;
  598.                                                 Pkt->dp_Res1=DOSTRUE;
  599.                                                 PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  600.                                         break;
  601.  
  602.                                         case ACTION_READ:
  603.                                         Pkt->dp_Res1=0;
  604. #ifdef DEBUG
  605.                                         PktFPuts(Inst,DebugFile,"Got action_read\n");
  606. #endif
  607.                                         AddTail(&ReadWaitList,Msg);
  608.                                         break;
  609.  
  610.                                         case ACTION_WRITE:
  611. #ifdef DEBUG
  612.                                         PktFPuts(Inst,DebugFile,"Got action_write\n");
  613. #endif
  614.                                         SockWrite(Inst,Socket,(char *)Pkt->dp_Arg2,Pkt->dp_Arg3,FALSE/*RawMode*/);
  615.                                         Pkt->dp_Res1=Pkt->dp_Arg3;
  616.                                         PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  617.                                         break;
  618.  
  619.                                         case ACTION_WAIT_CHAR:
  620. #ifdef DEBUG
  621.                                                 PktFPuts(Inst,DebugFile,"Got action_waitchar");
  622. #endif
  623.                                                 Pkt->dp_Res1=DOSFALSE;
  624.  
  625.                                                 TimeReq=CreateIORequest(TimePort,sizeof(struct timerequest));
  626.                                                 if (!TimeReq || OpenDevice("timer.device",UNIT_MICROHZ,TimeReq,0)) {
  627.                                                         if (TimeReq)
  628.                               DeleteIORequest(TimeReq);
  629.                                                         Pkt->dp_Res2=ERROR_NO_FREE_STORE;
  630.                                                         PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  631.                                                 }
  632.                                                 TimeReq->tr_node.io_Command=TR_ADDREQUEST;
  633.                                                 TimeReq->tr_time.tv_micro=Pkt->dp_Arg1;
  634.                                                 TimeReq->tr_time.tv_secs=0;
  635.                                                 TimeReq->tr_node.io_Message.mn_Node.ln_Name=Msg;
  636.                                                 SendIO(TimeReq);
  637.                                                 Pkt->dp_Res2=(ULONG)TimeReq;
  638.  
  639.                                                 AddTail(&ReadWaitList,Msg);
  640.  
  641.                                         break;
  642.  
  643.         /*
  644.                                         case ACTION_DISKINFO:
  645.  
  646.                                         break;
  647.                                         */
  648.                                         case ACTION_SCREEN_MODE:
  649. #ifdef DEBUG
  650.                                         PktFPuts(Inst,DebugFile,"Got action_screen_mode\n");
  651. #endif
  652.                                                 if (Pkt->dp_Arg1) {
  653.                                                         /* Raw mode */
  654.                                                         SockPuts(Inst,Socket,NoEcho);
  655.                                                         RawMode=TRUE;
  656.                                                 } else {
  657.                                                         SockPuts(Inst,Socket,Echo);
  658.                                                         RawMode=FALSE;
  659.                                                 }
  660.                                                 Pkt->dp_Res1=DOSFALSE;
  661.                                                 PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  662.                                         break;
  663.  
  664.                                         case ACTION_END:
  665. #ifdef DEBUG
  666.                                         PktFPuts(Inst,DebugFile,"Got action_end\n");
  667. #endif
  668.                                                 Pkt->dp_Res1=0;
  669.                                                 PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  670.                                                 OpenCount--;
  671.                                                 if (!OpenCount) {
  672.                                                         for (GotMsg=(struct Message *)ReadWaitList.lh_Head;GotMsg->mn_Node.ln_Succ;GotMsg=(struct Message *)GotMsg->mn_Node.ln_Succ) {
  673.                                                                 Pkt=PktFromMsg(GotMsg);
  674.                                                                 if (Pkt->dp_Type==ACTION_WAIT_CHAR) {
  675.                                                                         AbortIO((struct IORequest *)Pkt->dp_Res2);
  676.                                                                         WaitIO((struct IORequest *)Pkt->dp_Res2);
  677.                                                                         CloseDevice((struct IORequest *)Pkt->dp_Res2);
  678.                                                                         DeleteIORequest((struct IORequest *)Pkt->dp_Res2);
  679.                                                                         Pkt->dp_Res2=0;
  680.                                                                 }
  681.                                                         }
  682.  
  683.                                                         goto quit;
  684.                                                 }
  685.                                         break;
  686.  
  687.                                         case ACTION_SEEK:
  688. #ifdef DEBUG
  689.                                         PktFPuts(Inst,DebugFile,"Got action_seek\n");
  690. #endif
  691.                                         Pkt->dp_Res1=-1;
  692.                                         Pkt->dp_Res2=ERROR_OBJECT_WRONG_TYPE;
  693.                                         PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  694.  
  695.                                         break;
  696.  
  697.  
  698.                                         default:
  699. #ifdef DEBUG
  700.                                         PktFPuts(Inst,DebugFile,"Got action_not_known. Number");
  701.                                         MakeLongStr(NumBuf,Pkt->dp_Type);
  702.                                         PktFPuts(Inst,DebugFile,NumBuf);
  703.                                         PktFPuts(Inst,DebugFile,"\n");
  704. #endif
  705.                                         Pkt->dp_Res1=0;
  706.                                         Pkt->dp_Res2=ERROR_ACTION_NOT_KNOWN;
  707.                                         PutMsg(Pkt->dp_Port,Pkt->dp_Link);
  708.                                 }
  709.                         }
  710.                 }
  711.         } else {
  712.                 /* Use fake serial */
  713.                 struct IOStdReq *IOReq=NULL;
  714.                 struct MsgPort *IOPort=NULL;
  715.                 struct FSRUnit *SerUnit=NULL;
  716.                 /* SerUnit->fsru_UserData[0]=CmdPort
  717.                    SerUnit->fsru_UserData[1]=ReadQueue
  718.                          SerUnit->fsru_UserData[2]=WriteQueue
  719.                          SerUnit->fsru_UserData[3]=Open count
  720.                          SerUnit->fsru_UserData[4]=RBufLen */
  721.                 struct MsgPort *CmdPort=NULL;
  722.                 struct List *ReadQueue=NULL;
  723.                 struct List *WriteQueue=NULL;
  724.                 char *CmdPtr;
  725.                 struct IOExtSer *GotReq=NULL,*OtrReq=NULL;
  726.                 char *RBuf=NULL;
  727.                 int RBufPos=0;
  728.                 int SerUnitAdded=FALSE;
  729.                 int Amnt;
  730.                 int RecvRet;
  731.                 int CD=TRUE; /* Carrier Detect */
  732.                 long UnitNum=FSR_UNITNONE;
  733.  
  734.                 /* We use IOExtSer.Status bit 0 as a flag to say whether this request has
  735.                    been aborted */
  736.  
  737. #ifdef DEBUG
  738.                 FPuts(DebugFile,"Creating ports...\n");
  739. #endif
  740.                 IOPort=CreateMsgPort();
  741.                 CmdPort=CreateMsgPort();
  742.                 IOReq=CreateIORequest(IOPort,sizeof(struct IOStdReq));
  743.                 if (!IOPort || !IOReq || !CmdPort) {
  744. #ifdef DEBUG
  745.                         FPuts(DebugFile,"Unable to create message port/IORequest\nExiting\n");
  746. #endif
  747.                         goto quitfakeser;
  748.                 }
  749. #ifdef DEBUG
  750.                 FPuts(DebugFile,"Opening fakesr.device...\n");
  751. #endif
  752.                 if (OpenDevice("fakesr.device",FSR_CTLUNIT,IOReq,0)) {
  753.                         IOReq->io_Device=NULL;
  754. #ifdef DEBUG
  755.                         FPuts(DebugFile,"Unable to open fakesr.device\nExiting\n");
  756. #endif
  757.                         goto quitfakeser;
  758.                 }
  759. #ifdef DEBUG
  760.                 FPuts(DebugFile,"opened successfully\n");
  761. #endif
  762.                 SerUnit=AllocMem(sizeof(struct FSRUnit),MEMF_CLEAR|MEMF_PUBLIC);
  763.                 ReadQueue=AllocMem(sizeof(struct List),MEMF_PUBLIC);
  764.                 if (ReadQueue) NewList(ReadQueue);
  765.                 WriteQueue=AllocMem(sizeof(struct List),MEMF_PUBLIC);
  766.                 if (WriteQueue) NewList(WriteQueue);
  767.                 if (!SerUnit || !ReadQueue || !WriteQueue) {
  768. #ifdef DEBUG
  769.                         FPuts(DebugFile,"Unable to allocate memory\nExiting\n");
  770. #endif
  771.                         goto quitfakeser;
  772.                 }
  773.  
  774.                 CmdPtr=Info->Command;
  775.                 if (Info->Command[0]<='9' && Info->Command[0] >= '0') {
  776.                         UnitNum=GetInt(Info->Command,&CmdPtr);
  777.                 }
  778.  
  779.                 SerUnit->fsru_Num=UnitNum;
  780.                 SerUnit->fsru_BeginIO=FakeBeginIO;
  781.                 SerUnit->fsru_AbortIO=FakeAbortIO;
  782.                 SerUnit->fsru_Open=FakeOpen;
  783.                 SerUnit->fsru_Close=FakeClose;
  784.                 SerUnit->fsru_UserData[0]=CmdPort;
  785.                 SerUnit->fsru_UserData[1]=ReadQueue;
  786.                 SerUnit->fsru_UserData[2]=WriteQueue;
  787.                 SerUnit->fsru_UserData[3]=0;
  788.                 SerUnit->fsru_UserData[4]=(void *)1024;
  789.  
  790.                 IOReq->io_Data=(APTR)SerUnit;
  791.                 IOReq->io_Length=sizeof(*SerUnit);
  792.                 IOReq->io_Command=FSRCMD_ADDUNIT;
  793.                 IOReq->io_Error=0;
  794. #ifdef DEBUG
  795.                 FPuts(DebugFile,"Adding FakeSr unit...");
  796. #endif
  797.  
  798.                 DoIO(IOReq);
  799.                 if (IOReq->io_Error) {
  800. #ifdef DEBUG
  801.                         FPuts(DebugFile,"Error adding fakesr.device unit\nExiting\n");
  802. #endif
  803.                         goto quitfakeser;
  804.                 }
  805.  
  806.                 SerUnitAdded=TRUE;
  807.  
  808. #ifdef DEBUG
  809.                 FPuts(DebugFile,"Done\n");
  810. #endif
  811.  
  812.                 RBuf=AllocMem((ULONG)SerUnit->fsru_UserData[4],MEMF_PUBLIC);
  813.                 RBufPos=0;
  814.                 if (!RBuf) {
  815. #ifdef DEBUG
  816.                         FPuts(DebugFile,"Unable to allocate memory\nExiting\n");
  817. #endif
  818.                         goto quitfakeser;
  819.                 }
  820.  
  821.  
  822.                 IoctlSocket(Socket,FIONBIO,(caddr_t)&yes);
  823.                 {
  824.                         BPTR NilInput,NilOutput;
  825. #ifdef DEBUG
  826.                         FPuts(DebugFile,"Opening filehandles\n");
  827. #endif
  828.       if (*CmdPtr) {
  829.                           NilInput=Open("NIL:",MODE_OLDFILE);
  830.                           NilOutput=Open("NIL:",MODE_OLDFILE);
  831.  
  832.                           /* sprintf(Buf,"%s -DEVICE fakesr.device -UNIT %ld",CmdPtr,SerUnit->fsru_Num); */
  833.                           strcpy(Buf,CmdPtr);
  834.                           mystrcat(Buf," -DEVICE fakesr.device -UNIT ");
  835.                           MakeLongStr(LoginBuf,SerUnit->fsru_Num);
  836. #ifdef DEBUG
  837.                           FPuts(DebugFile,"Got FakeSr unit: ");
  838.                           FPuts(DebugFile,LoginBuf);
  839.                           FPuts(DebugFile,"\n");
  840. #endif
  841.                           SockPuts(Inst,Socket,NoEcho);
  842.  
  843.                           mystrcat(Buf,LoginBuf);
  844. #ifdef DEBUG
  845.                           FPuts(DebugFile,"Running command:");
  846.                           FPuts(DebugFile,Buf);
  847.                           FPuts(DebugFile,"\n");
  848. #endif
  849.                           MySystemTags(DOSBase,Buf,SYS_Input,NilInput,SYS_Output,NilOutput,SYS_Asynch,TRUE,TAG_END);
  850.       }
  851.                 }
  852.  
  853.                 for (;;) {
  854.                         FD_ZERO(&RdSet);
  855.                         FD_ZERO(&WrSet);
  856.                         if (CD)  {
  857.                                 if (RBufPos < (((long)SerUnit->fsru_UserData[4])-1)) FD_SET(Socket,&RdSet);
  858.                                 if (WriteQueue->lh_Head->ln_Succ) FD_SET(Socket,&WrSet);
  859.                         }
  860.                         SigMask=(1<<CmdPort->mp_SigBit)|SIGBREAKF_CTRL_C;
  861.                         WaitSelect(Socket+1,&RdSet,&WrSet,NULL,NULL,&SigMask);
  862. #ifdef DEBUG
  863.                         FPuts(DebugFile,"Wait ended...");
  864. #endif
  865.  
  866.                         if (FD_ISSET(Socket,&RdSet)) {
  867.                                 while ((RBufPos < (long)SerUnit->fsru_UserData[4]) && ((RecvRet=RecvChar(Inst,Socket,RBuf+RBufPos,TRUE))==1)) RBufPos++;
  868.                                 Forbid();
  869.                                 if ((GotReq=(struct IOExtSer *)ReadQueue->lh_Head)->IOSer.io_Message.mn_Node.ln_Succ) {
  870.                                         Remove(GotReq);
  871.                                         Permit();
  872.                                         Amnt=min(RBufPos,GotReq->IOSer.io_Length);
  873.                                         memcpy(((char *)GotReq->IOSer.io_Data)+GotReq->IOSer.io_Actual,RBuf,Amnt);
  874.                                         GotReq->IOSer.io_Actual+=Amnt;
  875.                                         if (Amnt < RBufPos) mymovmem(RBuf+Amnt,RBuf,RBufPos-Amnt);
  876.                                         RBufPos-=Amnt;
  877.  
  878.                                         if (GotReq->IOSer.io_Actual < GotReq->IOSer.io_Length) {
  879.                                                 if (GotReq->io_Status & (1<<0)) {
  880.                                                         /* We got an AbortIO() */
  881.                                                         GotReq->IOSer.io_Error=IOERR_ABORTED;
  882.                                                         ReplyMsg(GotReq);
  883.                                                 } else {
  884.                                                         Forbid();
  885.                                                         AddTail(ReadQueue,GotReq);
  886.                                                         Permit();
  887.                                                 }
  888.                                         }
  889.                                         else ReplyMsg(GotReq);
  890.  
  891.                                 }
  892.                                 else Permit();
  893.                                 if (RecvRet==0) {
  894.                                         /* Connection closed */
  895.                                         CD=FALSE;
  896.                                 }
  897.                         }
  898.                         if (FD_ISSET(Socket,&WrSet)) {
  899.                                 Forbid();
  900.                                 if ((GotReq=(struct IOExtSer *)WriteQueue->lh_Head)->IOSer.io_Message.mn_Node.ln_Succ) {
  901.                                         Remove(GotReq);
  902.                                         Permit();
  903.  
  904. #ifdef DEBUG
  905.                                         FPuts(DebugFile,"Writing to socket\n");
  906.                                         MyFPrintf(Inst,DebugFile,"io_Actual=%ld,io_Length=%ld\n",(long)GotReq->IOSer.io_Actual,(long)GotReq->IOSer.io_Length);
  907. #endif
  908.                                         SockWrite(Inst,Socket,((char *)GotReq->IOSer.io_Data)+GotReq->IOSer.io_Actual,GotReq->IOSer.io_Length-GotReq->IOSer.io_Actual,TRUE);
  909. #ifdef DEBUG
  910.                                         FPuts(DebugFile,"Write completed\n");
  911. #endif
  912.                                         GotReq->IOSer.io_Actual=GotReq->IOSer.io_Length;
  913.  
  914.  
  915.                                         if (GotReq->IOSer.io_Actual < GotReq->IOSer.io_Length) {
  916.                                                 Forbid();
  917.                                                 if (GotReq->io_Status & (1<<0)) {
  918.                                                         Permit();
  919.                                                         /* We got an AbortIO() */
  920.                                                         GotReq->IOSer.io_Error=IOERR_ABORTED;
  921.                                                         ReplyMsg(GotReq);
  922.                                                 } else {
  923.                                                         AddTail(WriteQueue,GotReq);
  924.                                                         Permit();
  925.                                                 }
  926.                                         } else {
  927. #ifdef DEBUG
  928.                                                 FPuts(DebugFile,"Replying write message\n");
  929. #endif
  930.                                                 ReplyMsg(GotReq);
  931.                                         }
  932.  
  933.  
  934.                                 } else {
  935.  
  936.                                         Permit();
  937.                                 }
  938.                         }
  939.                         while (GotReq=(struct IOExtSer *)GetMsg(CmdPort)) {
  940.                                 if (GotReq->IOSer.io_Message.mn_Node.ln_Name==Signature) {
  941.                                         /* We just use the pointer as a signature */
  942.                                         /* We just got an expunge request */
  943. #ifdef DEBUG
  944.                                         FPuts(DebugFile,"Got expunge request\n");
  945. #endif
  946.  
  947.                                         FreeMem(GotReq,sizeof(struct Message)); /* We free the expunge request instead of reply */
  948.  
  949.                                         Forbid();
  950.                                         if (SerUnit->fsru_UserData[3]==0) {
  951.                                                 /* Open count==0 */
  952.                                                 if (SerUnitAdded) {
  953.                                                         IOReq->io_Command=FSRCMD_REMUNIT;
  954.                                                         IOReq->io_Data=(APTR)SerUnit;
  955.                                                         IOReq->io_Length=sizeof(*SerUnit);
  956.                                                         DoIO(IOReq);
  957.                                                         SerUnitAdded=FALSE;
  958.                                                 }
  959.                                                 if (SerUnit->fsru_UserData[3]==0) {
  960.                                                         /* If opencnt is still 0 */
  961.                                                         Permit();
  962.                                                         goto quitfakeser; /* exit */
  963.                                                 }
  964.                                         }
  965.                                         Permit();
  966.                                 }
  967.                                 else {
  968. #ifdef DEBUG
  969.                                         FPuts(DebugFile,"Got cmd...");
  970. #endif
  971.  
  972.                                         switch(GotReq->IOSer.io_Command) {
  973.                                                 case CMD_CLEAR:
  974. #ifdef DEBUG
  975.                                                         FPuts(DebugFile,"Got CMD_CLEAR\n");
  976. #endif
  977.                                                         RBufPos=0;
  978.                                                         GotReq->IOSer.io_Error=0;
  979.                                                         ReplyMsg(GotReq);
  980.                                                 break;
  981.  
  982.                                                 case CMD_FLUSH:
  983.                                                 case CMD_RESET:
  984. #ifdef DEBUG
  985.                                                         FPuts(DebugFile,"Got CMD_FLUSH/RESET\n");
  986. #endif
  987.  
  988.                                                         Forbid();
  989.                                                         while (OtrReq=(struct IOExtSer *)RemHead(ReadQueue)) {
  990.                                                                 OtrReq->IOSer.io_Error=IOERR_ABORTED;
  991.                                                                 ReplyMsg(OtrReq);
  992.                                                         }
  993.                                                         while (OtrReq=(struct IOExtSer *)RemHead(WriteQueue)) {
  994.                                                                 OtrReq->IOSer.io_Error=IOERR_ABORTED;
  995.                                                                 ReplyMsg(OtrReq);
  996.                                                         }
  997.                                                         Permit();
  998.                                                         GotReq->IOSer.io_Error=0;
  999.                                                         ReplyMsg(GotReq);
  1000.                                                 break;
  1001.  
  1002.                                                 case CMD_READ:
  1003. #ifdef DEBUG
  1004.                                                         FPuts(DebugFile,"Got CMD_READ\n");
  1005. #endif
  1006.  
  1007.                                                         GotReq->IOSer.io_Actual=0;
  1008.                                                         GotReq->IOSer.io_Error=0;
  1009.                                                         Amnt=min(RBufPos,GotReq->IOSer.io_Length);
  1010.                                                         memcpy(((char *)GotReq->IOSer.io_Data)+GotReq->IOSer.io_Actual,RBuf,Amnt);
  1011.                                                         GotReq->IOSer.io_Actual+=Amnt;
  1012.                                                         if (Amnt < RBufPos) mymovmem(RBuf+Amnt,RBuf,Amnt);
  1013.                                                         RBufPos-=Amnt;
  1014.  
  1015.                                                         if (GotReq->IOSer.io_Actual < GotReq->IOSer.io_Length) {
  1016.                                                                 Forbid();
  1017.                                                                 AddTail(ReadQueue,GotReq);
  1018.                                                                 Permit();
  1019.                                                         }
  1020.                                                         else ReplyMsg(GotReq);
  1021.                                                 break;
  1022.  
  1023.                                                 case CMD_START:
  1024. #ifdef DEBUG
  1025.                                                         FPuts(DebugFile,"Got CMD_START\n");
  1026. #endif
  1027.  
  1028.                                                         GotReq->IOSer.io_Error=0;
  1029.                                                         ReplyMsg(GotReq);
  1030.                                                 break;
  1031.  
  1032.                                                 case CMD_STOP:
  1033. #ifdef DEBUG
  1034.                                                         FPuts(DebugFile,"Got CMD_STOP\n");
  1035. #endif
  1036.  
  1037.                                                         GotReq->IOSer.io_Error=0;
  1038.                                                         ReplyMsg(GotReq);
  1039.                                                 break;
  1040.  
  1041.                                                 case CMD_WRITE:
  1042. #ifdef DEBUG
  1043.                                                         FPuts(DebugFile,"Got CMD_WRITE\n");
  1044. #endif
  1045.  
  1046.                                                         GotReq->IOSer.io_Actual=0;
  1047.                                                         GotReq->IOSer.io_Error=0;
  1048.                                                         Forbid();
  1049.                                                         AddTail(WriteQueue,GotReq);
  1050.                                                         Permit();
  1051.                                                 break;
  1052.  
  1053.                                                 case SDCMD_BREAK:
  1054. #ifdef DEBUG
  1055.                                                         FPuts(DebugFile,"Got SDCMD_BREAK\n");
  1056. #endif
  1057.  
  1058.                                                         GotReq->IOSer.io_Error=0;
  1059.                                                         ReplyMsg(GotReq);
  1060.                                                 break;
  1061.  
  1062.                                                 case SDCMD_QUERY:
  1063. #ifdef DEBUG
  1064.                                                         FPuts(DebugFile,"Got SDCMD_QUERY\n");
  1065. #endif
  1066.  
  1067.                                                         GotReq->IOSer.io_Actual=RBufPos;
  1068.                                                         GotReq->io_Status=0x0000 | ((CD) ? 0:(1<<5));
  1069.                                                         GotReq->IOSer.io_Error=0;
  1070.  
  1071.                                                         ReplyMsg(GotReq);
  1072.                                                 break;
  1073.  
  1074.                                                 case SDCMD_SETPARAMS:
  1075. #ifdef DEBUG
  1076.                                                         FPuts(DebugFile,"Got SDCMD_SETPARAMS\n");
  1077. #endif
  1078.  
  1079.                                                         GotReq->IOSer.io_Error=0;
  1080.                                                         ReplyMsg(GotReq);
  1081.                                                 break;
  1082.  
  1083.                                                 default:
  1084. #ifdef DEBUG
  1085.                                                         FPuts(DebugFile,"Got CMD_UNKNOWN\n");
  1086. #endif
  1087.                                                         GotReq->IOSer.io_Error=IOERR_NOCMD;
  1088.                                                         ReplyMsg(GotReq);
  1089.  
  1090.                                         }
  1091.                                 }
  1092.                         }
  1093.                 }
  1094.  
  1095.  
  1096.                 quitfakeser:
  1097.  
  1098.                 if (ReadQueue) {
  1099.                         Forbid();
  1100.                         while (GotReq=(struct IOExtSer *)RemHead(ReadQueue)) {
  1101.                                 GotReq->IOSer.io_Error=IOERR_ABORTED;
  1102.                                 GotReq->IOSer.io_Actual=0;
  1103.                                 ReplyMsg(GotReq);
  1104.                         }
  1105.                         Permit();
  1106.                         FreeMem(ReadQueue,sizeof(struct List));
  1107.                 }
  1108.                 if (WriteQueue) {
  1109.                         Forbid();
  1110.                         while (GotReq=(struct IOExtSer *)RemHead(WriteQueue)) {
  1111.                                 GotReq->IOSer.io_Error=IOERR_ABORTED;
  1112.                                 GotReq->IOSer.io_Actual=0;
  1113.                                 ReplyMsg(GotReq);
  1114.                         }
  1115.                         Permit();
  1116.                         FreeMem(WriteQueue,sizeof(struct List));
  1117.                 }
  1118.                 if (RBuf && SerUnit) {
  1119.                         FreeMem(RBuf,(long)SerUnit->fsru_UserData[4]);
  1120.                 }
  1121.                 if (SerUnit) {
  1122.                         if (SerUnitAdded && IOReq) {
  1123.                                 IOReq->io_Data=(APTR)SerUnit;
  1124.                                 IOReq->io_Length=sizeof(*SerUnit);
  1125.                                 IOReq->io_Command=FSRCMD_REMUNIT;
  1126.                                 DoIO(IOReq);
  1127.                         }
  1128.                         FreeMem(SerUnit,sizeof(struct FSRUnit));
  1129.                 }
  1130.                 if (IOReq) {
  1131.                         if (IOReq->io_Device) CloseDevice(IOReq);
  1132.                         DeleteIORequest(IOReq);
  1133.                 }
  1134.                 if (IOPort) DeleteMsgPort(IOPort);
  1135.                 if (CmdPort) DeleteMsgPort(CmdPort);
  1136.                 goto quit;
  1137.         }
  1138.  
  1139.         quit:
  1140. #ifdef DEBUG
  1141.         if (DebugFile) Close(DebugFile);
  1142. #endif
  1143.         SocketBaseTags(SBTM_SETVAL(SBTC_LOGTAGPTR), NULL, TAG_END);
  1144.         if (TimePort) DeleteMsgPort(TimePort);
  1145.         if (Info) FreeMem(Info,sizeof(struct PasswdInfo));
  1146.         if (Inst) {
  1147.                 if (UserGroupBase) CloseLibrary(UserGroupBase);
  1148.                 if (SocketBase) CloseLibrary(SocketBase);
  1149.                 if (UtilityBase) CloseLibrary(UtilityBase);
  1150.                 if (DOSBase) CloseLibrary(DOSBase);
  1151.         }
  1152.         return 0;
  1153. }
  1154.  
  1155. void MyFPrintf(struct InstData *Inst,BPTR File,char *Fmt,...)
  1156. {
  1157.         VFPrintf(File,Fmt,(&Fmt)+1);
  1158. }
  1159.  
  1160. void mystrcat(char *Dest,char *Cat)
  1161. {
  1162.         memcpy(Dest+strlen(Dest),Cat,strlen(Cat)+1);
  1163. }
  1164.  
  1165. void mymovmem(char *From,char *To,int Len)
  1166. {
  1167.         int Cnt;
  1168.         if (From > To) {
  1169.                 for (Cnt=0;Cnt < Len;Cnt++) {
  1170.                         To[Cnt]=From[Cnt];
  1171.                 }
  1172.         } else if (From < To) {
  1173.                 for (Cnt=Len-1;Cnt >= 0;Cnt--) {
  1174.                         To[Cnt]=From[Cnt];
  1175.                 }
  1176.         }
  1177. }
  1178.  
  1179. struct Node *FindNode(struct List *List,struct Node *Node)
  1180. /* returns Node if Node is a member of list, NULL otherwise */
  1181. {
  1182.         struct Node *ChkNode;
  1183.  
  1184.         for (ChkNode=List->lh_Head;ChkNode->ln_Succ;ChkNode=ChkNode->ln_Succ) {
  1185.                 if (ChkNode==Node) return Node;
  1186.         }
  1187.         return NULL;
  1188. }
  1189.  
  1190. ULONG FakeBeginIO(void *IORequest)
  1191. {
  1192.         ((struct IORequest *)IORequest)->io_Flags &= ~IOF_QUICK; /* Quick IO not supported */
  1193.         ((struct IOExtSer *)IORequest)->io_Status &= ~(1<<0); /* clear abort bit */
  1194.         ((struct Node *)IORequest)->ln_Name=NULL; /* clear possible signature */
  1195.         PutMsg((struct MsgPort *)((struct FSRUnit *)((struct IORequest *)IORequest)->io_Unit)->fsru_UserData[0],IORequest);
  1196.         return 0;
  1197. }
  1198.  
  1199. ULONG FakeAbortIO(void *IORequest)
  1200. {
  1201.         struct IOExtSer *Ser;
  1202.  
  1203.         Ser=IORequest;
  1204.         Forbid();
  1205.                 Ser->io_Status |= (1<<0); /* Flag the request as aborted */
  1206.                 if (FindNode(((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[1],Ser) ||
  1207.                         FindNode(((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[2],Ser)) {
  1208.                                 /* This IORequest is waiting to be processed */
  1209.                                 Remove(Ser);
  1210.                                 Ser->IOSer.io_Error=IOERR_ABORTED;
  1211.                                 Ser->IOSer.io_Actual=0;
  1212.                                 ReplyMsg(Ser);
  1213.                 }
  1214.                 else {
  1215.                         /* This IORequest is currently being processed -- send a break */
  1216.                         Signal(((struct MsgPort *)((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[0])->mp_SigTask,SIGBREAKF_CTRL_C);
  1217.                 }
  1218.         Permit();
  1219.  
  1220.         return 0;
  1221. }
  1222.  
  1223. ULONG FakeOpen(void *IORequest)
  1224. {
  1225.         struct IOExtSer *Ser;
  1226.  
  1227.         Ser=IORequest;
  1228.         Forbid();
  1229.         ((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[3]=(void *) ((long)(((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[3])+1); /* Increment opencnt */
  1230.         Permit();
  1231.         Ser->IOSer.io_Error=0;
  1232.         Ser->io_CtlChar=SER_DEFAULT_CTLCHAR;
  1233.         Ser->io_RBufLen=(long)((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[4];
  1234.         Ser->io_ExtFlags=0;
  1235.         Ser->io_Baud=19200;
  1236.         Ser->io_BrkTime=250000;
  1237.         Ser->io_TermArray.TermArray0=0;
  1238.         Ser->io_TermArray.TermArray1=0;
  1239.         Ser->io_ReadLen=8;
  1240.         Ser->io_WriteLen=8;
  1241.         Ser->io_StopBits=1;
  1242.         Ser->io_Status=0;
  1243.         return 0;
  1244. }
  1245.  
  1246. ULONG FakeClose(void *IORequest)
  1247. {
  1248.         struct IOExtSer *Ser;
  1249.         struct Message *Msg;
  1250.  
  1251.         Ser=IORequest;
  1252.         Forbid();
  1253.  
  1254.         ((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[3]=(void *) ((long)(((struct FSRUnit *)Ser->IOSer.io_Unit)->fsru_UserData[3])-1); /* Decrement opencnt */
  1255.         Msg=AllocMem(sizeof(struct Message),MEMF_PUBLIC|MEMF_CLEAR);
  1256.         Msg->mn_Node.ln_Name=Signature;
  1257.         PutMsg((struct MsgPort *)((struct FSRUnit *)((struct IORequest *)IORequest)->io_Unit)->fsru_UserData[0],Msg);
  1258.  
  1259.         Permit();
  1260.         return 0;
  1261. }
  1262.  
  1263.  
  1264. struct DosPacket *PktFromMsg(struct Message *Msg)
  1265. {
  1266.         return (struct DosPacket *)Msg->mn_Node.ln_Name;
  1267. }
  1268.  
  1269. void PktFPuts(struct InstData *Inst,BPTR File,char *String)
  1270. {
  1271.         struct MsgPort *ReplyPort;
  1272.         struct DosPacket *Pkt;
  1273.  
  1274.         ReplyPort=CreateMsgPort();
  1275.         Pkt=AllocDosObject(DOS_STDPKT,NULL);
  1276.         if (!Pkt || !ReplyPort) return;
  1277.  
  1278.         Pkt->dp_Type=ACTION_WRITE;
  1279.         Pkt->dp_Arg1=((struct FileHandle *)BADDR(File))->fh_Arg1;
  1280.         Pkt->dp_Arg2=(LONG) String;
  1281.         Pkt->dp_Arg3=strlen(String);
  1282.         Pkt->dp_Port=ReplyPort;
  1283.         PutMsg(((struct FileHandle *)BADDR(File))->fh_Type,Pkt->dp_Link);
  1284.         WaitPort(ReplyPort);
  1285.         GetMsg(ReplyPort);
  1286.         DeleteMsgPort(ReplyPort);
  1287.         FreeDosObject(DOS_STDPKT,Pkt);
  1288. }
  1289.  
  1290. unsigned long GetInt(char *String,char **NewPtr)
  1291. {
  1292.         unsigned long Num=0;
  1293.         char *Junk;
  1294.         long Cnt;
  1295.         long BaseNum;
  1296.  
  1297.         if (!NewPtr) NewPtr=&Junk;
  1298.  
  1299.         for (*NewPtr=String;;(*NewPtr)++) {
  1300.  
  1301.                 if (**NewPtr < '0' || **NewPtr > '9') return Num;
  1302.  
  1303.                 /* AAARGH!! multiplication causes a lib call to be generated.
  1304.                    We can't use the library. Therefore we have to add */
  1305.                 /* Num=Num*10; */
  1306.                 for (BaseNum=Num,Cnt=0;Cnt < 9;Cnt++,Num+=BaseNum);
  1307.  
  1308.  
  1309.                 Num+=**NewPtr-'0';
  1310.         }
  1311.  
  1312. }
  1313.  
  1314.  
  1315. void SockPuts(struct InstData *Inst,int Sock,char *Buf)
  1316. {
  1317.         int BufPos=0;
  1318.         int BytesWritten;
  1319.  
  1320.         do {
  1321.                 BytesWritten=send(Sock,Buf+BufPos,strlen(Buf+BufPos),0);
  1322.                 if (BytesWritten > 0) BufPos+=BytesWritten;
  1323.         } while (Buf[BufPos]);
  1324. }
  1325.  
  1326. void SockRawWrite(struct InstData *Inst,int Sock,char *Buf,int Len)
  1327. {
  1328.         int BufPos=0;
  1329.         int BytesWritten;
  1330.  
  1331.         if (!Len) return;
  1332.  
  1333.         do {
  1334.                 BytesWritten=send(Sock,Buf+BufPos,Len-BufPos,0);
  1335.                 if (BytesWritten > 0) BufPos+=BytesWritten;
  1336.         } while (Len-BufPos);
  1337.  
  1338. }
  1339.  
  1340. void SockWrite(struct InstData *Inst,int Sock,char *Buf,int Len,int RawFlag)
  1341. {
  1342.         int Cnt;
  1343.         int BufPos=0;
  1344.         unsigned char iac2[2];
  1345.         char eol[2];
  1346.         char csi[2];
  1347.         iac2[0]=iac2[1]=IAC;
  1348.         eol[0]='\r';
  1349.         eol[1]='\n';
  1350.         csi[0]='\x1b';
  1351.         csi[1]='[';
  1352.  
  1353.  
  1354.         while (Len > BufPos) {
  1355.                 for (Cnt=BufPos;Cnt < Len;Cnt++) {
  1356.                         if (!RawFlag)
  1357.                                 if (Buf[Cnt]=='\r' || Buf[Cnt]=='\n') break;
  1358.                                 if (Buf[Cnt]=='\x9b') break;
  1359.                         if (Buf[Cnt]==IAC) {
  1360.                                 break;
  1361.                         }
  1362.                 }
  1363.                 SockRawWrite(Inst,Sock,Buf+BufPos,Cnt-BufPos);
  1364.                 BufPos=Cnt;
  1365.                 if (BufPos < Len && Buf[BufPos]==IAC) { /* If we got single IAC, send double IAC */
  1366.                         BufPos++;
  1367.                         SockRawWrite(Inst,Sock,iac2,2);
  1368.                 }
  1369.                 if (!RawFlag) {
  1370.                         if (BufPos < Len && Buf[BufPos]=='\r') {
  1371.                                 BufPos++;
  1372.                         }
  1373.                         if (BufPos < Len && Buf[BufPos]=='\n') {
  1374.                                 BufPos++;
  1375.                                 SockRawWrite(Inst,Sock,eol,2);
  1376.                         }
  1377.                         if (BufPos < Len && Buf[BufPos]=='\x9b') {
  1378.                                 BufPos++;
  1379.                                 SockRawWrite(Inst,Sock,csi,2);
  1380.                         }
  1381.                 }
  1382.         }
  1383. }
  1384.  
  1385. void ParseBuf3(struct InstData *Inst)
  1386. /* Parse 3 character remote request */
  1387. {
  1388.  
  1389. }
  1390.  
  1391. void ParseBuf2(struct InstData *Inst)
  1392. /* Parse 2 character remote-request */
  1393. {
  1394.  
  1395. }
  1396.  
  1397. void ParseBufSubNegotiate(struct InstData *Inst)
  1398. {
  1399.  
  1400. }
  1401.  
  1402. int RecvChar(struct InstData *Inst,int Sock,unsigned char *Loc,int RawMode)
  1403. {
  1404.         int GotLen;
  1405.         unsigned char Got,TrueGot;
  1406.         /*RawMode=TRUE;*/
  1407.         static unsigned char PrevChar;
  1408.  
  1409.         do {
  1410.  
  1411.                 GotLen=recv(Sock,&Got,1,0); /* Wait for a character */
  1412.                 if (GotLen==-1) {
  1413.                         if (Errno()==EINTR) continue;
  1414.                         else return -1;
  1415.                 } else if (GotLen==0) return 0;
  1416.  
  1417.                 TrueGot=Got;
  1418.                 if (!Inst->RecvBufPos && GotLen==1 && Got==0) GotLen=-1; /* Read again */
  1419.                 if (GotLen==1 && !RawMode && !Inst->RecvBufPos) {
  1420.                         /* These next few lines ignore incoming newlines and convert
  1421.                         incoming CRs into newlines   */
  1422.                         if (Got=='\n' && PrevChar=='\r') GotLen=-1; /* Read again. */
  1423.                         if (Got=='\r') Got='\n';
  1424.                 }
  1425.         } while (GotLen != 1);
  1426. /*      *Loc=Got;
  1427.         return 1; */
  1428.  
  1429.         if (Inst->RecvBufPos) {
  1430.                 Inst->RecvBuf[Inst->RecvBufPos]=Got;
  1431.                 Inst->RecvBufPos++;
  1432.                 switch (Inst->RecvBufPos) {
  1433.                         case 2:
  1434.                           switch(Inst->RecvBuf[1]) {
  1435.                                         case IAC:
  1436.                                           /* Just a single IAC */
  1437.                                                 *Loc=IAC;
  1438.                                                 return 1;
  1439.                                         break;
  1440.  
  1441.                                         case SB:
  1442.                                                 Inst->RecvBufFlags|=RBF_SUBNEGOTIATE;
  1443.                                                 return RecvChar(Inst,Sock,Loc,RawMode);
  1444.                                         break;
  1445.  
  1446.                                         case SE:
  1447.                                         Inst->RecvBufPos=0;
  1448.                                         Inst->RecvBufFlags &= ~RBF_SUBNEGOTIATE;
  1449.                                         return RecvChar(Inst,Sock,Loc,RawMode);
  1450.  
  1451.                                         case WILL:
  1452.                                         case WONT:
  1453.                                         case DO:
  1454.                                         case DONT:
  1455.                                         return RecvChar(Inst,Sock,Loc,RawMode);
  1456.                                         break;
  1457.  
  1458.                                         default:
  1459.                                         ParseBuf2(Inst);
  1460.                                         Inst->RecvBufPos=0;
  1461.                                         return RecvChar(Inst,Sock,Loc,RawMode);
  1462.                                 }
  1463.                         break;
  1464.  
  1465.                         default:
  1466.                                 if (Inst->RecvBufFlags & RBF_SUBNEGOTIATE) {
  1467.                                         if (Inst->RecvBufPos >= 2 && Inst->RecvBuf[Inst->RecvBufPos-2]==IAC && Inst->RecvBuf[Inst->RecvBufPos-1]!=IAC) {
  1468.                                                 /* End of subnegotiation */
  1469.                                                 Inst->RecvBuf[0]=IAC;
  1470.                                                 if ((Inst->RecvBuf[1]=Inst->RecvBuf[Inst->RecvBufPos-1])==SE) {
  1471.                                                         Inst->RecvBufFlags &= ~RBF_SUBNEGOTIATE;
  1472.                                                         Inst->RecvBufPos=0;
  1473.                                                         return RecvChar(Inst,Sock,Loc,RawMode);
  1474.                                                 }
  1475.                                                 Inst->RecvBufPos=2;
  1476.  
  1477.                                                 ParseBufSubNegotiate(Inst);
  1478.                                         }
  1479.  
  1480.                                         if (Inst->RecvBufPos >= 2 && Inst->RecvBuf[Inst->RecvBufPos-2]==IAC && Inst->RecvBuf[Inst->RecvBufPos-1]==IAC) {
  1481.                                                 /* We just got a double IAC in subnegotiation */
  1482.                                                 Inst->RecvBuf[Inst->RecvBufPos-2]=-1; /* We store IAC as a (int)-1 */
  1483.                                                 Inst->RecvBufPos--;
  1484.                                         }
  1485.                                         return RecvChar(Inst,Sock,Loc,RawMode);
  1486.                                 } else {
  1487.                                         if (Inst->RecvBuf[2]==IAC) {
  1488.                                                 /* Restart sequence */
  1489.                                                 Inst->RecvBuf[0]=IAC;
  1490.                                                 Inst->RecvBufPos=1;
  1491.                                                 return RecvChar(Inst,Sock,Loc,RawMode);
  1492.                                         } else {
  1493.                                           ParseBuf3(Inst);
  1494.                                                 Inst->RecvBufPos=0;
  1495.                                                 return RecvChar(Inst,Sock,Loc,RawMode);
  1496.                                         }
  1497.                                 }
  1498.                         break;
  1499.                 }
  1500.         }
  1501.         else {
  1502.                 if (Got==IAC) {
  1503.                         Inst->RecvBuf[0]=Got;
  1504.                         Inst->RecvBufPos=1;
  1505.                         return RecvChar(Inst,Sock,Loc,RawMode);
  1506.                 } else {
  1507.                         *Loc=Got;
  1508.                         PrevChar=TrueGot;
  1509.                         return 1;
  1510.                 }
  1511.         }
  1512.         return 1;
  1513.  
  1514. }
  1515.  
  1516.  
  1517. void SockGets(struct InstData *Inst,int Sock,char *Buf,int BufSize)
  1518. /* This function gets the next string until a CR
  1519. on the specified socket, and places it in buf. It
  1520. discards leading crs/lfs */
  1521. {
  1522.         int BufPos=0;
  1523.         int BytesRead;
  1524.         int FirstBytes=TRUE;
  1525.         Buf[0]='\0';
  1526.  
  1527.         do {
  1528.                 BytesRead=RecvChar(Inst,Sock,Buf+BufPos,FALSE);
  1529.                 if (BytesRead < 0) {
  1530.                         if (Errno()!=EINTR) {
  1531.                                 Buf[BufPos]='\0';
  1532.                                 return;
  1533.                         }
  1534.           }
  1535.                 else if (BytesRead==0) {
  1536.                         Buf[BufPos]='\0';
  1537.                         return;
  1538.                 }
  1539.                 else {
  1540.                         if ((Buf[BufPos]=='\r' || Buf[BufPos]=='\n') && FirstBytes) {
  1541.                                 Buf[BufPos]='\0';
  1542.                         } else {
  1543.                                 FirstBytes=FALSE;
  1544.                                 BufPos+=BytesRead;
  1545.                         }
  1546.                 }
  1547.         } while (Buf[BufPos-1] != '\r' && Buf[BufPos-1] != '\n' && BufPos < (BufSize-1));
  1548.         Buf[BufPos]='\0';
  1549. }
  1550.  
  1551. char *PullPasswdString(char **StringPtr)
  1552. {
  1553.         int Cnt;
  1554.         char *RetVal;
  1555.         char *CurPos;
  1556.  
  1557.         if (!StringPtr || !*StringPtr) return NULL;
  1558.  
  1559.         RetVal=*StringPtr;
  1560.  
  1561.         for (CurPos=RetVal;*CurPos != ',' && *CurPos != '\r' && *CurPos != '\n' && *CurPos;CurPos++);
  1562.         switch (*CurPos) {
  1563.                 case ',':
  1564.                 case '\r':
  1565.                 case '\n':
  1566.                         *CurPos='\0';
  1567.                         CurPos++;
  1568.                         *StringPtr=CurPos;
  1569.                 return RetVal;
  1570.  
  1571.                 case '\0':
  1572.                 *StringPtr=CurPos;
  1573.                 return RetVal;
  1574.         }
  1575. }
  1576.  
  1577. int mystrcmp(char *S1,char *S2)
  1578. {
  1579.         int Cnt;
  1580.         for (Cnt=0;S1[Cnt] && S2[Cnt];Cnt++) {
  1581.                 if (S1[Cnt] != S2[Cnt]) return !0;
  1582.         }
  1583.         if (S1[Cnt] != S2[Cnt]) return !0;
  1584.         return 0;
  1585. }
  1586.  
  1587. struct PasswdInfo *LookupPasswd(struct InstData *Inst,char *Login)
  1588. {
  1589.         BPTR File;
  1590.         char *LineBuf;
  1591.         char *BufPtr;
  1592.         char *PasswdPtr;
  1593.         char *LoginPtr;
  1594.         char *RealNamePtr;
  1595.         char *HomeDirPtr;
  1596.         char *CmdPtr;
  1597.         struct PasswdInfo *Info = NULL;
  1598.         struct passwd *result;
  1599.  
  1600.         if (result = getpwnam(Login)) {
  1601.                 if (Info=AllocMem(sizeof(struct PasswdInfo),MEMF_PUBLIC)) {
  1602.                         strcpy(Info->Login,result->pw_name);
  1603.                         strcpy(Info->Passwd,result->pw_passwd);
  1604.                         strcpy(Info->RealName,result->pw_gecos);
  1605.                         strcpy(Info->Command,result->pw_shell);
  1606.                 }
  1607.                 else
  1608.                         syslog(LOG_CRIT, "Couldn't allocate my info structure!");
  1609.         }
  1610.         else
  1611.                 syslog(LOG_INFO, "user %s is unknown here", Login);
  1612.  
  1613.         return Info;
  1614. }
  1615.  
  1616. void __asm PutMLSChar(register __d0 char Chr,register __a3 char **BufPtr)
  1617. {
  1618.         **BufPtr=Chr;
  1619.         (*BufPtr)++;
  1620. }
  1621.  
  1622. void MakeLongStr(char *StrBuf,unsigned long Num)
  1623. {
  1624.         RawDoFmt("%lu",&Num,PutMLSChar,&StrBuf);
  1625. }
  1626.  
  1627.  
  1628. struct Process *MyCreateNewProcTags(struct InstData *Inst,ULONG Tag1,...)
  1629. {
  1630.         return CreateNewProc((struct TagItem *)&Tag1);
  1631. }
  1632.  
  1633. void *MyAllocDosObjectTags(struct InstData *Inst,ULONG Type,ULONG Tag1,...)
  1634. {
  1635.         return AllocDosObject(Type,(struct TagItem *)&Tag1);
  1636. }
  1637. void MySystemTags(struct Library *DSBse,char *Cmd,ULONG Tag0,...)
  1638. {
  1639. #undef DOSBase
  1640. #define DOSBase DSBse
  1641.         SystemTagList(Cmd,(struct TagItem *)&Tag0);
  1642. #undef DOSBase
  1643. }
  1644.  
  1645. #define DOSBase DSBse
  1646. int __asm __saveds SubSubProc(register __a0 char *ArgString,register __d0 long Length)
  1647. {
  1648.         char StringBuf[1000];
  1649.         char *StringPtr;
  1650.         BPTR FH;
  1651.         struct Library *DSBse;
  1652.  
  1653.         DSBse=OpenLibrary("dos.library",36);
  1654.         if (!DSBse) return 0;
  1655.  
  1656.         FH=(BPTR)GetInt(ArgString,&StringPtr);
  1657.  
  1658. /*      if (IsInteractive(FH)) {
  1659.                 Write(FH,"Interactive\n",12);
  1660.         }*/
  1661.         strcpy(StringBuf,StringPtr);
  1662.     MySystemTags(DSBse,(StringBuf[0]) ? StringBuf : "execute S:remote-startup",
  1663.              SYS_Input,FH,
  1664.              SYS_Output,FH,
  1665.              NP_ConsoleTask,((struct FileHandle *)BADDR(FH))->fh_Type,
  1666.              NP_Cli,TRUE,
  1667.              TAG_END);
  1668.  
  1669.         Forbid();
  1670.         Close(FH);
  1671.         return 0;
  1672. }
  1673. #undef DOSBase
  1674.  
  1675. @
  1676.  
  1677.  
  1678. 1.11
  1679. log
  1680. @Minor cosmetic changes in the source code.
  1681. Added "user unknown" to the "getpwnam() failed" message, to
  1682. make sure that people don't misunderstand this as an error.
  1683. @
  1684. text
  1685. @d3 2
  1686. a4 2
  1687.  *      $Revision: 1.10 $
  1688.  *      $Date: 1995/02/03 00:25:28 $
  1689. d7 1
  1690. a7 1
  1691.  *      Copyright (C) 1995 by Peter Simons <simons@@peti.GUN.de>
  1692. d23 1
  1693. a23 1
  1694.  *      $Id: telnetd.c 1.10 1995/02/03 00:25:28 simons Exp simons $
  1695. d98 1
  1696. a98 1
  1697. static const char __DOSVer[] = VERSTAG " written by Peter Simons <simons@@peti.GUN.de>";
  1698. d143 1
  1699. a143 1
  1700.         char Buf[1000],LoginBuf[50];
  1701. d310 2
  1702. d320 4
  1703. d358 2
  1704. a359 3
  1705.                           NP_Arguments,Buf,
  1706.                           NP_Name,"Telnet subprocess",
  1707.                           TAG_END);
  1708. d1527 1
  1709. a1527 1
  1710.                 syslog(LOG_DEBUG, "getpwnam() failed, user unknown");
  1711. d1578 6
  1712. a1583 13
  1713.         if (!StringBuf[0]) {
  1714.                 MySystemTags(DSBse,"execute s:remote-startup",
  1715.                         SYS_Input,FH,
  1716.                         SYS_Output,FH,
  1717.                         NP_ConsoleTask,((struct FileHandle *)BADDR(FH))->fh_Type,
  1718.                         TAG_END);
  1719.         } else {
  1720.                 MySystemTags(DSBse,StringBuf,
  1721.                         SYS_Input,FH,
  1722.                         SYS_Output,FH,
  1723.                         NP_ConsoleTask,((struct FileHandle *)BADDR(FH))->fh_Type,
  1724.                         TAG_END);
  1725.         }
  1726. @
  1727.  
  1728.  
  1729. 1.10
  1730. log
  1731. @Modified telnetd to use usergroup.library's routines to access
  1732. the passwd file. Thus, I had to insert UserGroupBase into the
  1733. Inst-structure holding the various library bases.
  1734. Modified telnetd to block any login where the user has no valid
  1735. shell provided. Any shell us accepted except "nologin".
  1736. Added initializations for syslog().
  1737. Reformatted source code a bit.
  1738. @
  1739. text
  1740. @d3 2
  1741. a4 2
  1742.  *      $Revision: 1.9 $
  1743.  *      $Date: 1995/01/26 22:20:38 $
  1744. d23 1
  1745. a23 1
  1746.  *      $Id: telnetd.c 1.9 1995/01/26 22:20:38 simons Exp simons $
  1747. d424 2
  1748. a425 1
  1749.                                                         if (Pkt->dp_Res1==Pkt->dp_Arg3 || Chr=='\r' || Chr=='\n') {
  1750. d427 3
  1751. d538 2
  1752. a539 1
  1753.                                                         if (TimeReq) DeleteIORequest(TimeReq);
  1754. d1522 1
  1755. a1522 1
  1756.                 syslog(LOG_DEBUG, "getpwnam() failed");
  1757. @
  1758.  
  1759.  
  1760. 1.9
  1761. log
  1762. @Removed an unnecessary declaration. Doesn't really affect the code.
  1763. @
  1764. text
  1765. @d3 2
  1766. a4 2
  1767.  *      $Revision: 1.8 $
  1768.  *      $Date: 1995/01/24 00:12:47 $
  1769. d23 1
  1770. a23 1
  1771.  *      $Id: telnetd.c 1.8 1995/01/24 00:12:47 simons Exp simons $
  1772. d39 1
  1773. d48 2
  1774. d60 1
  1775. d77 1
  1776. d79 1
  1777. a79 1
  1778. #define UtilityBase Inst->UtilityB
  1779. d207 2
  1780. d212 7
  1781. a218 1
  1782.         if (!DOSBase || !UtilityBase || !SocketBase || !TimePort) return 0;
  1783. d287 2
  1784. a288 2
  1785.   Info=LookupPasswd(Inst,LoginBuf);
  1786.   if (!Info || strcmp(Info->Passwd,"*")) {
  1787. d290 25
  1788. a314 18
  1789.           strcpy(Buf,"Password: ");
  1790.           strcpy(Buf+strlen(Buf),NoEcho);
  1791.           SockPuts(Inst,Socket,Buf);
  1792.           SockGets(Inst,Socket,Buf,sizeof(Buf));
  1793.           while (strlen(Buf) && (Buf[strlen(Buf)-1]=='\n' || Buf[strlen(Buf)-1]=='\r'))
  1794.                 Buf[strlen(Buf)-1]='\0';
  1795.           SockPuts(Inst,Socket,Echo);
  1796. #ifdef DEBUG
  1797.           FPuts(DebugFile,"Got Password: ");
  1798.           FPuts(DebugFile,Buf);
  1799.           FPuts(DebugFile,"\n");
  1800. #endif
  1801.           if (!Info || strcmp(Buf,Info->Passwd)) {
  1802.                   SockPuts(Inst,Socket,"\nLogin incorrect.\nClosing connection\n");
  1803.                   CloseSocket(Socket);
  1804.                   goto quit;
  1805.           }
  1806.   }
  1807. d1049 1
  1808. d1053 1
  1809. d1503 2
  1810. a1504 5
  1811.         struct PasswdInfo *Info;
  1812.         /* int NoPasswd=FALSE; */
  1813.  
  1814.         LineBuf=AllocMem(1000,MEMF_PUBLIC);
  1815.         if (!LineBuf) return NULL;
  1816. d1506 6
  1817. a1511 43
  1818.         File=Open("AmiTCP:db/telnetd_passwd",MODE_OLDFILE);
  1819.         if (!File) return NULL;
  1820.  
  1821.  
  1822.         while (FGets(File,LineBuf,1000)) {
  1823.                 if (LineBuf[0]=='#') continue;
  1824.                 BufPtr=LineBuf;
  1825.                 LoginPtr=PullPasswdString(&BufPtr);
  1826. #ifdef DEBUG
  1827.                 FPuts(DebugFile,"Got username: ");
  1828.                 FPuts(DebugFile,LoginPtr);
  1829.                 FPuts(DebugFile,"\n");
  1830. #endif
  1831.                 PasswdPtr=PullPasswdString(&BufPtr);
  1832. #ifdef DEBUG
  1833.                 FPuts(DebugFile,"Got password: ");
  1834.                 FPuts(DebugFile,PasswdPtr);
  1835.                 FPuts(DebugFile,"\n");
  1836. #endif
  1837.                 PullPasswdString(&BufPtr); /* throw away user id */
  1838.                 PullPasswdString(&BufPtr); /* Throw away group id */
  1839.                 RealNamePtr=PullPasswdString(&BufPtr);
  1840.                 HomeDirPtr=PullPasswdString(&BufPtr);
  1841.                 CmdPtr=PullPasswdString(&BufPtr);
  1842.  
  1843.                 /* if (!mystrcmp(PasswdPtr,"*")) NoPasswd=TRUE;*//*strcpy(Passwd,PasswdPtr);*/
  1844.     /* else NoPasswd=FALSE; */
  1845.                 if (!mystrcmp(Login,LoginPtr)) {
  1846. #ifdef DEBUG
  1847.                         FPuts(DebugFile,"Password located\n");
  1848. #endif
  1849.                         /* Password located and correct */
  1850.                         /*if (CmdPtr[0]=='*') */ /* We only support stdin/out logins */
  1851.                         Close(File);
  1852.                         Info=AllocMem(sizeof(struct PasswdInfo),MEMF_PUBLIC);
  1853.                         if (!Info) return NULL;
  1854.                         strcpy(Info->Login,LoginPtr);
  1855.                         strcpy(Info->Passwd,PasswdPtr);
  1856.                         strcpy(Info->RealName,RealNamePtr);
  1857.                         strcpy(Info->WorkDir,HomeDirPtr);
  1858.                         strcpy(Info->Command,CmdPtr);
  1859.                         FreeMem(LineBuf,1000);
  1860.                         return Info;
  1861. d1513 2
  1862. d1516 4
  1863. a1519 3
  1864.         Close(File);
  1865.         FreeMem(LineBuf,1000);
  1866.         return NULL; /* Login failed */
  1867. @
  1868.  
  1869.  
  1870. 1.8
  1871. log
  1872. @Renamed tnserv:passwd to AmiTCP:db/telnetd_passwd.
  1873. Renamed tnserv:banner to AmiTCP:db/telnetd_banner.
  1874. These names are subject of change.
  1875. Re-wrote the routine that copied the banner file to use
  1876. Read() rather than FGets().
  1877. Change to telnetd to accept if no banner file is available.
  1878. Earlier versions would have terminated.
  1879. @
  1880. text
  1881. @d3 2
  1882. a4 2
  1883.  *      $Revision: 1.7 $
  1884.  *      $Date: 1995/01/23 23:51:39 $
  1885. d23 1
  1886. a23 1
  1887.  *      $Id: telnetd.c 1.7 1995/01/23 23:51:39 simons Exp simons $
  1888. a92 1
  1889. //struct Library *SocketBase;
  1890. @
  1891.  
  1892.  
  1893. 1.7
  1894. log
  1895. @Renamed the daemon to telnetd. Getty sounds like a BBS. :-)
  1896. @
  1897. text
  1898. @d3 2
  1899. a4 2
  1900.  *      $Revision: 1.6 $
  1901.  *      $Date: 1995/01/23 23:42:48 $
  1902. d23 1
  1903. a23 1
  1904.  *      $Id: telnetd.c 1.6 1995/01/23 23:42:48 simons Exp simons $
  1905. d248 10
  1906. a257 7
  1907.         BannerFile=Open("tnserv:banner",MODE_OLDFILE);
  1908.         if (!BannerFile) goto quit;
  1909. #ifdef DEBUG
  1910.         FPuts(DebugFile,"Opened tnserv:banner\n");
  1911. #endif
  1912.         while (FGets(BannerFile,Buf,sizeof(Buf))) {
  1913.                 SockWrite(Inst,Socket,Buf,strlen(Buf),FALSE);
  1914. d259 1
  1915. d261 1
  1916. a261 1
  1917.         FPuts(DebugFile,"Wrote tnserv:banner to socket\n");
  1918. a1031 1
  1919.         if (BannerFile) Close(BannerFile);
  1920. d1488 1
  1921. a1488 1
  1922.         File=Open("tnserv:Passwd",MODE_OLDFILE);
  1923. @
  1924.  
  1925.  
  1926. 1.6
  1927. log
  1928. @Adding the weird assignment of the message to the name pointer again.
  1929. Obviously, Steve was using this hack as a shurtcut to provide an
  1930. additional parameter to a subroutine without having to worry about
  1931. adding an entry to his structure. I will fix this some day. Not
  1932. very high priority.
  1933. @
  1934. text
  1935. @d2 3
  1936. a4 3
  1937.  *      $Filename: TelnetGetty.c $
  1938.  *      $Revision: 1.5 $
  1939.  *      $Date: 1995/01/23 23:35:13 $
  1940. d23 1
  1941. a23 1
  1942.  *      $Id: TelnetGetty.c 1.5 1995/01/23 23:35:13 simons Exp simons $
  1943. d50 1
  1944. a50 1
  1945. #include "TelnetGetty_rev.h"
  1946. d208 2
  1947. a209 2
  1948.         DebugFile=Open("con:0/0/500/100/TelnetGetty DEBUG/WAIT/CLOSE",MODE_OLDFILE);
  1949.         FPuts(DebugFile,"TelnetGetty starting\n");
  1950. @
  1951.  
  1952.  
  1953. 1.5
  1954. log
  1955. @Made the Echo[], NoEcho[] and iac2[] arrays unsigned character
  1956. to avoid compiler warnings when assigning values above 128.
  1957. Removed some multiuser.library stuff.
  1958. Minor fix when compiling with USE_INETD: Debug output tried
  1959. to print an uninitialized auto variable.
  1960. Didn't test the returncode of LookupPasswd(), causing an enforcer
  1961. hit when no correct login had been specified.
  1962. @
  1963. text
  1964. @d3 2
  1965. a4 2
  1966.  *      $Revision: 1.3 $
  1967.  *      $Date: 1995/01/23 22:19:28 $
  1968. d23 1
  1969. a23 1
  1970.  *      $Id: TelnetGetty.c 1.3 1995/01/23 22:19:28 simons Exp simons $
  1971. d518 1
  1972. a518 1
  1973.                                                 /* TimeReq->tr_node.io_Message.mn_Node.ln_Name=Msg; TODO */
  1974. @
  1975.  
  1976.  
  1977. 1.4
  1978. log
  1979. @Added several casts to avoid warnings.
  1980. Removed weird assignment of an Message structure to the
  1981. name field of a TimerRequest. Made no sense to me.
  1982. @
  1983. text
  1984. @d145 2
  1985. a146 2
  1986.         char NoEcho[7];
  1987.         char Echo[14];
  1988. a171 8
  1989. /*
  1990.         Echo[0]=NoEcho[0]=IAC;
  1991.         Echo[1]=WONT;
  1992.         Echo[2]=ECHO;
  1993.         NoEcho[1]=WILL;
  1994.         NoEcho[2]=ECHO;
  1995.         Echo[3]=NoEcho[3]='\0';
  1996. */
  1997. d209 3
  1998. a211 1
  1999.         FPuts(DebugFile,"TelnetGetty starting\nArgString=");
  2000. d214 1
  2001. d286 1
  2002. a286 1
  2003.           if (strcmp(Buf,Info->Passwd)) {
  2004. a292 19
  2005.  
  2006. /*
  2007.         if (muBase) {
  2008.                 struct TagItem tags[]={
  2009.                         {muT_Graphical,FALSE},
  2010.                         {muT_Task,NULL},
  2011.                         {muT_Global,FALSE},
  2012.                         /*{muT_Quiet,FALSE},*/
  2013.                         /* {muT_All,FALSE}, */
  2014.                         {muT_UserID,NULL},
  2015.                         {muT_Password,NULL},
  2016.                         {TAG_END,0}
  2017.                 };
  2018.                 tags[1].ti_Data=FindTask(NULL);
  2019.                 tags[5].ti_Data=LoginBuf;
  2020.                 tags[6].ti_Data=Buf;
  2021.                 muLoginA(tags);
  2022.         }
  2023.         */
  2024. d1226 1
  2025. a1226 1
  2026.         char iac2[2];
  2027. d1558 1
  2028. @
  2029.  
  2030.  
  2031. 1.3
  2032. log
  2033. @Fixed a bug when compiling in USE_INETD mode: The ReadWaitList-
  2034. queue hasn't been initialized. Moved the NewList() out of the
  2035. #ifdef-#else statement to fix this.
  2036. @
  2037. text
  2038. @d3 2
  2039. a4 2
  2040.  *      $Revision: 1.2 $
  2041.  *      $Date: 1995/01/23 21:59:56 $
  2042. d23 1
  2043. a23 1
  2044.  *      $Id: TelnetGetty.c 1.2 1995/01/23 21:59:56 simons Exp simons $
  2045. d224 1
  2046. a224 1
  2047.         Self=FindTask(NULL);
  2048. d251 1
  2049. d542 1
  2050. a542 1
  2051.                                                 TimeReq->tr_node.io_Message.mn_Node.ln_Name=Msg;
  2052. d579 1
  2053. a579 1
  2054.                                                         for (GotMsg=ReadWaitList.lh_Head;GotMsg->mn_Node.ln_Succ;GotMsg=(struct Message *)GotMsg->mn_Node.ln_Succ) {
  2055. d1186 1
  2056. a1186 1
  2057.         Pkt->dp_Arg2=String;
  2058. d1623 1
  2059. @
  2060.  
  2061.  
  2062. 1.2
  2063. log
  2064. @Made source compile with SAS/C 6.51.
  2065. Restructured source code basically and added GNU copyleft header.
  2066. Renamed SubProcCode() to main().
  2067. Removed some multiuser.library stuff.
  2068. @
  2069. text
  2070. @d3 2
  2071. a4 2
  2072.  *      $Revision$
  2073.  *      $Date$
  2074. d23 1
  2075. a23 1
  2076.  *      $Id$
  2077. d98 1
  2078. a98 1
  2079. const char *Signature="FAKEMSG--EXPUNGE";
  2080. d212 1
  2081. a228 1
  2082.  
  2083. a230 1
  2084.         NewList(&ReadWaitList);
  2085. @
  2086.  
  2087.  
  2088. 1.1
  2089. log
  2090. @Initial revision
  2091. @
  2092. text
  2093. @d1 25
  2094. a25 1
  2095. /* #define CLIB_SOCKET_INLINES_H        / * avoid that include file */
  2096. d27 1
  2097. d32 1
  2098. a48 4
  2099. /*#include <libraries/multiuser.h>
  2100. #include <proto/multiuser.h>
  2101. */
  2102. /* IMPORTANT: Do NOT link this module with the startup code */
  2103. d50 3
  2104. a60 2
  2105. /* Defines for RecvBufFlags: */
  2106. #define RBF_SUBNEGOTIATE (1<<0)
  2107. d63 7
  2108. a69 8
  2109. #undef DEBUG
  2110.  
  2111. struct Library *SocketBase; /* Linker wants it. We don't use it */
  2112. #ifndef USE_INETD
  2113. struct Library *SysBase;
  2114. #endif
  2115.  
  2116. const char *Signature="FAKEMSG--EXPUNGE";
  2117. d71 1
  2118. d90 9
  2119. a98 7
  2120. struct PasswdInfo {
  2121.         char Login[50];
  2122.         char Passwd[50];
  2123.         char RealName[150];
  2124.         char WorkDir[256];
  2125.         char Command[512];
  2126. };
  2127. d100 1
  2128. d125 1
  2129. a125 2
  2130. #define bzero(base,n) memset(base,0,n)
  2131. #define bcopy(from,to,n) memcpy(to,from,n)
  2132. a129 1
  2133. /* SubProcCode MUST be the first function in the file */
  2134. d131 1
  2135. a131 1
  2136. void main(void)
  2137. d133 1
  2138. a133 1
  2139. int __asm SubProcCode(register __a0 char *ArgStr,register __d0 long Length)
  2140. a163 1
  2141.         /*struct Library *muBase=NULL;*/
  2142. a210 3
  2143. /*      muBase=OpenLibrary("multiuser.library",39);*/
  2144.  
  2145.  
  2146. d1588 1
  2147. a1588 1
  2148. int __asm SubSubProc(register __a0 char *ArgString,register __d0 long Length)
  2149. @
  2150.